/*****************************************************************************/
/**
*
* @file uiicps.c
*
* User defined functions about iic.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver   Who    Date   	Changes
* ----- ---- ---------- -------------------------------------------------------
* 0.01  abu  05/20/2019 Created
* </pre>
*
*------------------------------------------------------------------------------
* Author: abu	E-mail:	abu_liu@aliyun.com
*				Blog:	https://blog.csdn.net/ClamerKorallen
*				Gitee:	https://gitee.com/abu_liu
*------------------------------------------------------------------------------
*
******************************************************************************/
#include "uiicps.h"
#include "uinterrupt.h"
#include "debug.h"

/************************** Function Prototypes ******************************/

/*****************************************************************************/
/**
*
* Set iic0 to a known state.
*
*
* @param	Instance_ptr is a pointer to XIicPs.
* @param	DeviceId is the id of the device to be initialized
*
* @return	None.
*
* @note		None.
*
******************************************************************************/

void uIicPsInit(XIicPs *Instance_ptr, u32 DeviceId)
{
	s32 status;
	XIicPs_Config *cfg_ptr;
	
	cfg_ptr = XIicPs_LookupConfig(DeviceId);
	XIicPs_CfgInitialize(Instance_ptr, cfg_ptr, cfg_ptr->BaseAddress);

	status = (s32)XST_FAILURE;
	status = XIicPs_SelfTest(Instance_ptr);
	if (status != XST_SUCCESS) {
		DEBUG("CPU iic initialization failed\n\r");
		DEBUG_POS();
	}

	status = (s32)XST_FAILURE;
	status = XIicPs_SetOptions(Instance_ptr, XIICPS_7_BIT_ADDR_OPTION);
	if (status != XST_SUCCESS) {
		DEBUG("CPU iic initialization failed\n\r");
		DEBUG_POS();
	}

	uIicPsIntrSetup(Instance_ptr);
	XIicPs_SetStatusHandler(Instance_ptr, (void *) Instance_ptr, uIic0PsHandler);

	status = (s32)XST_FAILURE;
	status = XIicPs_SetSClk(Instance_ptr, UIIC_SCLK_100KHZ);
	if (status != XST_SUCCESS) {
		DEBUG("CPU iic initialization failed\n\r");
		DEBUG_POS();
	}

}

/******************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the IIC.
*
* @param	IicPsPtr contains a pointer to the instance of the Iic
*		which is going to be connected to the interrupt controller.
*
* @return	XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note		None.
*
*******************************************************************************/
void uIicPsIntrSetup(XIicPs *IicPsPtr)
{
	int status;
	XScuGic *scugic_dev_ptr = &uScuGic;

	//ensure device has been initialized
	Xil_AssertNonvoid(IicPsPtr->IsReady == XIL_COMPONENT_IS_READY);
	Xil_AssertNonvoid(scugic_dev_ptr->IsReady == XIL_COMPONENT_IS_READY);

	/*
	 * Connect iic interrupt handler to GIC
	 */
	if(IicPsPtr->Config.DeviceId == UIIC0_DEV_ID)
		status = XScuGic_Connect(scugic_dev_ptr, UIIC0_INTR_ID,
				(Xil_InterruptHandler)XIicPs_MasterInterruptHandler,
				(void *)IicPsPtr);
/*	else if(IicPsPtr->Config.DeviceId == UIIC1_DEV_ID)
			status = XScuGic_Connect(scugic_dev_ptr, UIIC1_INTR_ID,
				(Xil_InterruptHandler)XIicPs_MasterInterruptHandler,
				(void *)IicPsPtr);
*/
	if (status != XST_SUCCESS) {
		DEBUG("CPU iic0 initialization failed\n\r");
		DEBUG_POS();

	}

	/*
	 * Enable the interrupt for the Iic device.
	 */
	if(IicPsPtr->Config.DeviceId == UIIC0_DEV_ID)
		XScuGic_Enable(scugic_dev_ptr, UIIC0_INTR_ID);
	else
		XScuGic_Enable(scugic_dev_ptr, UIIC1_INTR_ID);

}

/*****************************************************************************/
/**
* Default status handler, copied from bsp.
*
* This function is the handler which performs processing to handle data events
* from the IIC.  It is called from an interrupt context such that the amount
* of processing performed should be minimized.
*
* This handler provides an example of how to handle data for the IIC and
* is application specific.
*
* @param	CallBackRef contains a callback reference from the driver, in
*		this case it is the instance pointer for the IIC driver.
* @param	Event contains the specific kind of event that has occurred.
*
* @return	None.
*
* @note		None.
*
*******************************************************************************/
void uIic0PsHandler(void *CallBackRef, u32 Event)
{
	/*
	 * All of the data transfer has been finished.
	 */
	if (0 != (Event & XIICPS_EVENT_COMPLETE_RECV)){
		uIic0TransStatus.RecvComplete = TRUE;
	} else if (0 != (Event & XIICPS_EVENT_COMPLETE_SEND)) {
		uIic0TransStatus.SendComplete = TRUE;
	} else if (0 == (Event & XIICPS_EVENT_SLAVE_RDY)){
		/*
		 * If it is other interrupt but not slave ready interrupt, it is
		 * an error.
		 * Data was received with an error.
		 */
		uIic0TransStatus.TotalErrorCount++;
	}
}

/*****************************************************************************/
/**
* Default status handler, copied from bsp.
*
* This function is the handler which performs processing to handle data events
* from the IIC.  It is called from an interrupt context such that the amount
* of processing performed should be minimized.
*
* This handler provides an example of how to handle data for the IIC and
* is application specific.
*
* @param	CallBackRef contains a callback reference from the driver, in
*		this case it is the instance pointer for the IIC driver.
* @param	Event contains the specific kind of event that has occurred.
*
* @return	None.
*
* @note		None.
*
*******************************************************************************/
void uIic1PsHandler(void *CallBackRef, u32 Event)
{
	/*
	 * All of the data transfer has been finished.
	 */
	if (0 != (Event & XIICPS_EVENT_COMPLETE_RECV)){
		uIic1TransStatus.RecvComplete = TRUE;
	} else if (0 != (Event & XIICPS_EVENT_COMPLETE_SEND)) {
		uIic1TransStatus.SendComplete = TRUE;
	} else if (0 == (Event & XIICPS_EVENT_SLAVE_RDY)){
		/*
		 * If it is other interrupt but not slave ready interrupt, it is
		 * an error.
		 * Data was received with an error.
		 */
		uIic1TransStatus.TotalErrorCount++;
	}
}


